using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Permissions;
using System.Web;
using System.Web.Mvc;
using AutoMapper;
using good1.Core.Enums;
using good1.Web.Controllers.Attributes;
using good1.Web.Controllers.Infrastructure;
using good1.Web.Controllers.Infrastructure.Cookies;
using good1.Web.Model;
using good1.ApplicationServices.Dto;
using good1.ApplicationServices.Interface;
using good1.Core;
using good1.Web.Controllers.Utility;
using SharpArch.Web.NHibernate;
using SharpArch.Web.CommonValidator;
using SharpArch.Core;

namespace good1.Web.Controllers
{
    public class ProjectsController : BaseController
    {
        private readonly string photoFolder = System.Configuration.ConfigurationManager.AppSettings["PhotoDirectory"] ?? "/content/images/photo";

        public ProjectsController(IProjectService<ProjectDto> projectService, ISecurityContextService securityContext) : base(securityContext)
        {
            Check.Require(projectService != null, "projectService may not be null");
            
            this.projectService = projectService;

            Mapper.CreateMap<DateTime, string>().ConvertUsing(new MapperHelper.DateTimeTypeConverter());
        }

        [Transaction]
        public ActionResult Index()
        {
            ProjectListView projectListView = CreateViewData<ProjectListView>();
            IList<Project> projects = projectService.GetAllSorted();
            Mapper.CreateMap<Project, ProjectListItem>();
            projectListView.ProjectList = Mapper.Map<IList<Project>, IList<ProjectListItem>>(projects); ;
            return View(projectListView);
        }

        //TODO http://blog.codeville.net/  let's bring in XVal now for client side validation that 1.0 is released.

        [Transaction]
        public ActionResult Search(string q)
        {
            TempData["message"] = q;
            ProjectSearchView projectSearchView = CreateViewData<ProjectSearchView>();
            projectSearchView.SearchQuery = q;  
            IList<Project> projects = projectService.Search(q);
            Mapper.CreateMap<Project, ProjectListItem>();
            projectSearchView.ProjectList = Mapper.Map<IList<Project>, IList<ProjectListItem>>(projects); ;
            return View(projectSearchView);
        }

        [Transaction]
        [AuthorizeAttributeCustom(RoleRequired = GoodRoles.Nimda)]
        public ActionResult Admin()
        {
            ProjectListView projectListView = CreateViewData<ProjectListView>();
            IList<Project> projects = projectService.GetAllSorted();
            Mapper.CreateMap<Project, ProjectListItem>();
            projectListView.ProjectList = Mapper.Map<IList<Project>, IList<ProjectListItem>>(projects); ;
            return View(projectListView);
        }

        [Transaction]
        public ActionResult Show(int id) {
            ProjectDto projectDto = projectService.Get(id);
            Mapper.CreateMap<Project, ProjectDetailView>();
            ProjectDetailView projectDetailView = Mapper.Map<Project, ProjectDetailView>(projectDto.Project);
            projectDetailView = SetViewData(projectDetailView);
            return View(projectDetailView);
        }

        [Transaction]
        public ActionResult Map(int id)
        {
            ProjectDto projectDto = projectService.Get(id);
            Mapper.CreateMap<Project, ProjectDetailView>();
            ProjectDetailView projectDetailView = Mapper.Map<Project, ProjectDetailView>(projectDto.Project);
            projectDetailView = SetViewData(projectDetailView);
            return View(projectDetailView);
        }

        [Transaction]
        public ActionResult Details(int id)
        {
            ProjectDto projectDto = projectService.Get(id);
            Mapper.CreateMap<Project, ProjectDetailView>();
            ProjectDetailView projectDetailView = Mapper.Map<Project, ProjectDetailView>(projectDto.Project);
            projectDetailView = SetViewData(projectDetailView);
            return View(projectDetailView);
        }

        [Transaction]
        public ActionResult Photos(int id)
        {
            string name = SecurityContext.FriendlyName; //added this so testing covers injection of cookes
            ProjectDto projectDto = projectService.Get(id);
            Mapper.CreateMap<Project, ProjectDetail>();
            ProjectPhotosView projectPhotosView = CreateViewData<ProjectPhotosView>();
            projectPhotosView.ProjectDetail = Mapper.Map<Project, ProjectDetail>(projectDto.Project);
            Mapper.CreateMap<Photo, PhotoView>();
            projectPhotosView.Photos = Mapper.Map<IList<Photo>, IList<PhotoView>>(projectDto.Project.Photos);
            return View(projectPhotosView);
        }

        [Transaction]
        public ActionResult Costs(int id)
        {
            ProjectDto projectDto = projectService.Get(id);
            Mapper.CreateMap<Project, ProjectDetailView>();
            ProjectDetailView projectDetailView = Mapper.Map<Project, ProjectDetailView>(projectDto.Project);
            projectDetailView = SetViewData(projectDetailView);
            return View(projectDetailView);
        }

        [Transaction]
        public ActionResult Feedback(int id)
        {
            ProjectDto projectDto = projectService.Get(id);
            Mapper.CreateMap<Project, ProjectDetailView>();
            ProjectDetailView projectDetailView = Mapper.Map<Project, ProjectDetailView>(projectDto.Project);
            projectDetailView = SetViewData(projectDetailView);
            return View(projectDetailView);
        }

        [AuthorizeAttributeCustom(RoleRequired = GoodRoles.Nimda)]
        public ActionResult Create() {
           // string ip = HttpContext.Request.UserHostAddress;
            // if (ip == "127.0.0.1" || ip == "85.183.48.41")
            ProjectDto projectDto = projectService.GetCreationDto();
            return View(projectDto);
          }

        [AuthorizeAttributeCustom(RoleRequired = GoodRoles.Nimda)]
        public ActionResult ImageUpload()
        {
            ProjectDetailView projectDetailView = CreateViewData<ProjectDetailView>();
            return View(projectDetailView);
        }

        private void ReadFormCollectionIntoDto(ProjectDto projectDto, FormCollection formCollection)
        {
            projectDto.Project.Charity = !string.IsNullOrEmpty(formCollection["CharityList"]) ?
                    projectService.GetCharity(int.Parse(formCollection["CharityList"])) : null;
            projectDto.Project.Location = !string.IsNullOrEmpty(formCollection["LocationList"]) ?
               projectService.GetLocation(int.Parse(formCollection["LocationList"])) : null; 
        }

        [ValidateAntiForgeryToken]
        [AuthorizeAttributeCustom(RoleRequired = GoodRoles.Nimda)]
        [Transaction]
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Create(ProjectDto projectDto, FormCollection formCollection)
        {

            if (projectDto.Project.IsValid())
            {
                projectDto.Project.PhotoUrl = BuildPhotoPath(projectDto.Project.PhotoUrl);

                ReadFormCollectionIntoDto(projectDto, formCollection);

                projectService.SaveOrUpdate(projectDto.Project);

                TempData["message"] = "The project was successfully created.";
                return RedirectToAction("Admin");
            }

            MvcValidationAdapter.TransferValidationMessagesTo(ViewData.ModelState,
                projectDto.Project.ValidationResults());
            return View(projectDto);
        }

        private string BuildPhotoPath(string photoUrl)
        {
            if (photoUrl == null) return null;
            if (photoUrl.Contains(photoFolder)) return photoUrl;
            return Path.Combine(photoFolder, photoUrl);
        }

        [Transaction]
        [AuthorizeAttributeCustom(RoleRequired = GoodRoles.Nimda)]
        public ActionResult Edit(int id) {
            ProjectDto project = projectService.Get(id);
            return View(project);
        }

        [ValidateAntiForgeryToken]
        [Transaction]
        [AuthorizeAttributeCustom(RoleRequired = GoodRoles.Nimda)]
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Edit(int id, [ModelBinder(typeof(DefaultModelBinder))] ProjectDto projectDto, FormCollection formCollection) {
            ProjectDto projectToUpdate = projectService.Get(id);


            ReadFormCollectionIntoDto(projectToUpdate, formCollection);
            TransferFormValuesTo(projectToUpdate, projectDto);

            if (projectToUpdate.Project.IsValid()) {
                TempData["message"] = "The project was successfully updated.";
                return RedirectToAction("Admin");
            }
            else{
                projectService.RollbackTransaction();
                MvcValidationAdapter.TransferValidationMessagesTo(ViewData.ModelState, 
                    projectToUpdate.Project.ValidationResults());
                return View(projectToUpdate);
            }
        }

        private void TransferFormValuesTo(ProjectDto projectToUpdate, ProjectDto projectDto)
        {
            projectToUpdate.Project.Title = projectDto.Project.Title;
            projectToUpdate.Project.Text = projectDto.Project.Text;
            projectToUpdate.Project.ClosingDate = projectDto.Project.ClosingDate;
            projectToUpdate.Project.Amount = projectDto.Project.Amount;
            projectToUpdate.Project.AmountRemaining = projectDto.Project.AmountRemaining;
            projectToUpdate.Project.Priority = projectDto.Project.Priority;
            projectToUpdate.Project.TagLine = projectDto.Project.TagLine;
            projectToUpdate.Project.YourDonationCan = projectDto.Project.YourDonationCan;
            projectToUpdate.Project.PhotoUrl = BuildPhotoPath(projectDto.Project.PhotoUrl);
        }


        [ValidateAntiForgeryToken]
           [AcceptVerbs(HttpVerbs.Post)]
        [AuthorizeAttributeCustom(RoleRequired = GoodRoles.Nimda)]
            public ActionResult UploadProjectPhoto()
            {
               //todo write a test for this.  maybe put in different controller altogether?
                //http://www.hanselman.com/blog/ABackToBasicsCaseStudyImplementingHTTPFileUploadWithASPNETMVCIncludingTestsAndMocks.aspx
                if (Request.Files.Count > 0 && Request.Files[0].ContentLength > 0)
                {
                    //todo maybe resize http://stackoverflow.com/questions/662080/how-to-efficiently-scale-and-crop-images-in-an-asp-net-app
                    //will rely on user doing this for now in correct ratio.
                    HttpPostedFileBase image = Request.Files[0];
                    image.SaveAs(Path.Combine(Server.MapPath("~") + photoFolder, Path.GetFileName(image.FileName)));
                }
                return RedirectToAction("imageupload"); 
            }
        
        [ValidateAntiForgeryToken]
        [Transaction]
        [AuthorizeAttributeCustom(RoleRequired = GoodRoles.Nimda)]
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Delete(int id) {
            TempData["Message"] = projectService.Delete(id);
            return RedirectToAction("Index");
        }

     
        private readonly IProjectService<ProjectDto> projectService;
    }
}
